using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.IO;

namespace C4F.DevKit.PictureAcquisition
{
    /// <summary>
    /// Contains methods for management of picture acquisition.
    /// </summary>
    [ToolboxItem(true), ToolboxBitmap(typeof(PictureAcquisitionManager))]
    public class PictureAcquisitionManager : Component
    {
        #region Private members

        PictureAcquisitionNative.IPhotoAcquireItem photoAcquireItem;

        // Object for getting selected device information.
        DeviceInfo selectedDeviceInfo;

        // Error code returned from API method call.
        APIErrors errorResult;

        // Used to set and get file name template.
        string fileNameTemplate = "";

        bool CallBackMethod()
        {
            return false;
        }

        /// <summary>
        /// Creates temporary files.
        /// </summary>
        /// <param name="deviceId">Id of device , of which temporary file to be creted.</param>
        /// <returns>List of file names.</returns>
        List<string> CreateTemporaryFiles(string deviceId)
        {
            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;
            // Set to default value.
            errorResult = APIErrors.S_OK;

            List<string> imageName = new List<string>();

            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                UInt32 itemCount = 0;
                errorResult = (APIErrors)photoAcquireSource.InitializeItemList(true, IntPtr.Zero, out itemCount);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());
                
                for (int index = 0; index < itemCount; index++)
                {
                    System.Runtime.InteropServices.ComTypes.IStream comStream = null;

                    errorResult = (APIErrors)photoAcquireSource.GetItemAt((UInt32)index, out photoAcquireItem);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());
                    
                    // Get object of stream.
                    errorResult = (APIErrors)photoAcquireItem.GetStream(out comStream);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    System.Runtime.InteropServices.ComTypes.STATSTG comStreamInfo = new System.Runtime.InteropServices.ComTypes.STATSTG();

                    // Get information about retrieved stream object.
                    comStream.Stat(out comStreamInfo, 0);

                    byte[] bytes = new byte[comStreamInfo.cbSize];

                    // Read all bytes of stream in byte buffer.
                    comStream.Read(bytes, (int)comStreamInfo.cbSize, IntPtr.Zero);

                    imageName.Add(comStreamInfo.pwcsName);

                    if (!(Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + PictureAcquisitionResource.TempLocation)))
                        Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + PictureAcquisitionResource.TempLocation);

                    // Create a new file steram (file) at temporary location.
                    FileStream filestream = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + PictureAcquisitionResource.TempLocation + comStreamInfo.pwcsName, FileMode.OpenOrCreate);

                    // Write bytes of buffer in this new file.
                    filestream.Write(bytes, 0, (int)comStreamInfo.cbSize);

                    filestream.Close();

                    filestream.Dispose();

                    filestream = null;

                    if (comStream != null)
                        Marshal.ReleaseComObject(comStream);
                }
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                if (exception.Message == PictureAcquisitionResource.InvalidArg)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }
            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);

                if (photoAcquireItem != null)
                    Marshal.ReleaseComObject(photoAcquireItem);
            }
            return imageName;
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Creates an instance of PhotoAcquisitionManager class object.
        /// </summary>
        public PictureAcquisitionManager()
        {}

        #endregion

        #region Public methods

        #region AcquireItems

        /// <summary>
        /// Acquires picture and video items from specified device.
        /// </summary>
        /// <param name="deviceId">Id of device from which to acquire items.</param>
        /// <param name="showProgressDialog">Specifies whether progress dialog to be shown or not.</param>
        /// <returns>List of item names, actually acquired.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The specified parameter is not valid.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public List<string> AcquireItems(string deviceId, bool showProgressDialog)
        {
            // Check for null arguments.
            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            // Set to default value.
            errorResult = APIErrors.S_OK;

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            // Create object of IPhotoAcquireSettings.
            PictureAcquisitionNative.IPhotoAcquireSettings acquireSetting = null;


            List<string> itemsImportedList = new List<string>();
            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);


                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Create instance of IPhotoAcquireSettings.
                errorResult = (APIErrors)photoAcquireSource.GetPhotoAcquireSettings(out acquireSetting);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                Int32 progressBar = showProgressDialog == true ? 1 : 0;
                // Acquire items from specified device to the default location.
                errorResult = (APIErrors)photoAcquire.Acquire(photoAcquireSource, progressBar, IntPtr.Zero, "Test Application", IntPtr.Zero);

                if (errorResult != APIErrors.S_OK && errorResult != APIErrors.E_ABORT)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Create object of IEnumString.
                PictureAcquisitionNative.IEnumString enumstring;

                // Get enumeration of items actually acquired from specified device.
                errorResult = (APIErrors)photoAcquire.EnumResults(out enumstring);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Make list of items acquired.
                for (int index = 0; ; index++)
                {
                    string name;
                    uint fetched;

                    // Retrieve next item from enumeration.
                    errorResult = (APIErrors)enumstring.RemoteNext(1, out name, out  fetched);

                    if (errorResult == APIErrors.S_OK)
                    {
                        itemsImportedList.Add(name);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                if (exception.Message == PictureAcquisitionResource.InvalidArg)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }
            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);
            }

            return itemsImportedList;
        }

        /// <summary>
        /// Acquires picture and video items from specified device.
        /// </summary>
        /// <param name="deviceId">Id of device from which to acquire items.</param>
        /// <param name="showProgressDialog">Specifies progress dialog is to be shown or not.</param>
        /// <param name="targetLocation">Location for saving pictures of specified device.</param>
        /// <returns>List of item names, actually acquired.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The specified parameter is not valid.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public List<string> AcquireItems(string deviceId, bool showProgressDialog, string targetLocation)
        {
            if(string.IsNullOrEmpty(targetLocation))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterLocation);

            if (!Directory.Exists(targetLocation))
                Directory.CreateDirectory(targetLocation);

            // Check for null arguments.
            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            // Check for null or empty
            if (!string.IsNullOrEmpty(targetLocation))
            {
                // Check for maximum length of targetLocation.
                if (targetLocation.Length > 207)
                    throw new ArgumentException(PictureAcquisitionResource.TemplateMaxLength);
            }
            targetLocation += @"\$(OriginalFileName).$(OriginalExtension)";

            // Set to default value.
            errorResult = APIErrors.S_OK;

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            // Create object of IPhotoAcquireSettings.
            PictureAcquisitionNative.IPhotoAcquireSettings acquireSetting = null;


            List<string> itemsImportedList = new List<string>();
            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;
            
                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);


                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Create instance of IPhotoAcquireSettings.
                errorResult = (APIErrors)photoAcquireSource.GetPhotoAcquireSettings(out acquireSetting);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                if (!(string.IsNullOrEmpty(targetLocation)))
                {
                    // Set file name template.
                    errorResult = (APIErrors)acquireSetting.SetOutputFilenameTemplate(targetLocation);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    if (acquireSetting != null)
                        Marshal.ReleaseComObject(acquireSetting);
                }
                Int32 progressBar = showProgressDialog == true ? 1 : 0;
                // Acquire items from specified device to the default location.
                errorResult = (APIErrors)photoAcquire.Acquire(photoAcquireSource, progressBar, IntPtr.Zero, "Test Application", IntPtr.Zero);

                if (errorResult != APIErrors.S_OK && errorResult != APIErrors.E_ABORT)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Create object of IEnumString.
                PictureAcquisitionNative.IEnumString enumstring;

                // Get enumeration of items actually acquired from specified device.
                errorResult = (APIErrors)photoAcquire.EnumResults(out enumstring);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Make list of items acquired.
                for (int index = 0; ; index++)
                {
                    string name;
                    uint fetched;

                    // Retrieve next item from enumeration.
                    errorResult = (APIErrors)enumstring.RemoteNext(1, out name, out  fetched);

                    if (errorResult == APIErrors.S_OK)
                    {
                        itemsImportedList.Add(name);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                if (exception.Message == PictureAcquisitionResource.InvalidArg)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }
            finally
            {
                if(photoAcquireObject !=null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);                         
            }

            return itemsImportedList;
        }

        /// <summary>
        /// Acquires specified picture and video items from specified device at specified location.
        /// </summary>
        /// <param name="deviceId">Id of device from which to acquire items.</param>
        /// <param name="itemsToAcquire">List of item from device to acquire.</param>
        /// <param name="targetLocation">Target location , where items of device saved.</param>
        /// <returns>List of item names, actually acquired.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public List<string> AcquireItems(string deviceId, List<string> itemsToAcquire, string targetLocation)
        {
            // Check for null arguments.
            if (string.IsNullOrEmpty(targetLocation))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterLocation);

            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            if (itemsToAcquire == null)
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);
            else if (itemsToAcquire.Count == 0)
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            // Set to default value.        
            errorResult = APIErrors.S_OK;

            List<string> itemsImportedList = new List<string>();

            try
            {               
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                UInt32 itemCount = 0;
                errorResult = (APIErrors)photoAcquireSource.InitializeItemList(true, IntPtr.Zero, out itemCount);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                for (int index = 0; index < itemCount; index++)
                {
                    System.Runtime.InteropServices.ComTypes.IStream comStream = null;
                    errorResult = (APIErrors)photoAcquireSource.GetItemAt((UInt32)index, out photoAcquireItem);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    // Get object of stream.
                    errorResult = (APIErrors)photoAcquireItem.GetStream(out comStream);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    string itemName = null;
                    errorResult = (APIErrors)photoAcquireItem.GetItemName(out itemName);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    if (!itemsToAcquire.Contains(itemName))
                        continue;                  

                    System.Runtime.InteropServices.ComTypes.STATSTG comStreamInfo = new System.Runtime.InteropServices.ComTypes.STATSTG();

                    // Get information about retrieved stream object.
                    comStream.Stat(out comStreamInfo, 0);

                    byte[] bytes = new byte[comStreamInfo.cbSize];

                    // Read all bytes of stream in byte buffer.
                    comStream.Read(bytes, (int)comStreamInfo.cbSize, IntPtr.Zero);

                    if (!(Directory.Exists(targetLocation)))
                        Directory.CreateDirectory(targetLocation);

                    // Create a new file steram (file) at specified target location.
                    FileStream filestream = new FileStream(targetLocation + comStreamInfo.pwcsName, FileMode.Create);

                    // Write bytes of buffer in this new file.
                    filestream.Write(bytes, 0, (int)comStreamInfo.cbSize);

                    filestream.Close();

                    itemsImportedList.Add(comStreamInfo.pwcsName);

                    if (comStream != null)
                        Marshal.ReleaseComObject(comStream);
                }                
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                if (exception.Message == PictureAcquisitionResource.InvalidArg)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }
            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);
            }
            return itemsImportedList;
        }
        
        #endregion

        #region ShowDialog

        /// <summary>
        /// Takes handle of parent window for further use.
        /// </summary>
        /// <param name="handle">Hnadle of parent window.</param>
        /// <param name="dialogTitle">Title of device slection dialog.</param>
        /// <param name="submitButtonText">Text of submit button of device slection dialog.</param>
        public bool ShowAllDeviceDialog(IntPtr handle, string dialogTitle, string submitButtonText)
        {
            // Create the device selection dialog object.
            PictureAcquisitionNative.PhotoAcquireDeviceSelectionDialog dialogObject = null;
            PictureAcquisitionNative.IPhotoAcquireDeviceSelectionDialog selectDevice = null;

            // Check for null arguments.
            if (string.IsNullOrEmpty(dialogTitle))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDialogTitle);
            else if (string.IsNullOrEmpty(submitButtonText))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterSubmitButtonText);

            // Set to default value.
            errorResult = APIErrors.S_OK;

            bool doImort = false;
            string deviceID;
            UInt32 deviceType;

            try
            {
                dialogObject = new PictureAcquisitionNative.PhotoAcquireDeviceSelectionDialog();
                selectDevice = (PictureAcquisitionNative.IPhotoAcquireDeviceSelectionDialog)dialogObject;

                // Set text of submit button of device selection dialog.
                errorResult = (APIErrors)selectDevice.SetSubmitButtonText(submitButtonText);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Set title text of device selection dialog.
                errorResult = (APIErrors)selectDevice.SetTitle(dialogTitle);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Show device selection dialog and detect all devices in the device selection dialog.
                errorResult = (APIErrors)selectDevice.DoModal(handle, (uint)DeviceFlag.All, out deviceID, out deviceType);

                if (errorResult != APIErrors.S_OK && errorResult != APIErrors.E_ABORT)
                    throw new PictureAcquisitionException(errorResult.ToString());
                else
                {
                    if (errorResult == APIErrors.S_OK)
                    {
                        doImort = true;

                        // Create instance of object, if not already created.
                        this.selectedDeviceInfo = this.selectedDeviceInfo ?? new DeviceInfo();

                        // Set properties of selectedDeviceInfo object.
                        this.selectedDeviceInfo.Id = deviceID.ToString();
                        this.selectedDeviceInfo.Type = (DeviceType)deviceType;
                    }
                }

            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (dialogObject != null)
                    Marshal.ReleaseComObject(dialogObject);

                if (selectDevice != null)
                    Marshal.ReleaseComObject(selectDevice);
            }

            return doImort;
        }

        /// <summary>
        /// Shows specified devices in the device selection dialog window.
        /// </summary>
        /// <param name="handle">Handle of parent window.</param>
        /// <param name="devicesTypesToShow">Type of devices to be shown in device slection dialog.</param>
        /// <param name="dialogTitle">Title of device slection dialog.</param>
        /// <param name="submitButtonText">Text of submit button of device slection dialog.</param>
        /// <returns>Boolean indicating to do import or not. </returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public bool ShowDeviceSelectionDialog(IntPtr handle,DeviceFlag devicesTypesToShow, string dialogTitle, string submitButtonText)
        {
            // Create the device selection dialog object.
            PictureAcquisitionNative.PhotoAcquireDeviceSelectionDialog dialogObject = null;
            PictureAcquisitionNative.IPhotoAcquireDeviceSelectionDialog selectDevice = null;

            // Check for null arguments.
            if (string.IsNullOrEmpty(dialogTitle))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDialogTitle);
            else if (string.IsNullOrEmpty(submitButtonText))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterSubmitButtonText);

            // Set to default value.
            errorResult = APIErrors.S_OK;

            UInt32 deviceType;
            bool doImort = false;
            string deviceID;

            try
            {
                dialogObject = new PictureAcquisitionNative.PhotoAcquireDeviceSelectionDialog();
                selectDevice = (PictureAcquisitionNative.IPhotoAcquireDeviceSelectionDialog)dialogObject;

                // Set text of submit button of device selection dialog.
                errorResult = (APIErrors)selectDevice.SetSubmitButtonText(submitButtonText);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Set title text of device selection dialog.
                errorResult = (APIErrors)selectDevice.SetTitle(dialogTitle);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Show device selection dialog and detect only specified devices in the device selection dialog.
                errorResult = (APIErrors)selectDevice.DoModal(handle, (uint)devicesTypesToShow, out deviceID, out deviceType);

                if (errorResult != APIErrors.S_OK && errorResult != APIErrors.E_ABORT)
                    throw new PictureAcquisitionException(errorResult.ToString());
                else
                {
                    if (errorResult == APIErrors.S_OK)
                    {
                        doImort = true;

                        // Create instance of object, if not already created.
                        this.selectedDeviceInfo = this.selectedDeviceInfo ?? new DeviceInfo();

                        // Set properties of selectedDeviceInfo object.
                        this.selectedDeviceInfo.Id = deviceID.ToString();
                        this.selectedDeviceInfo.Type = (DeviceType)deviceType;
                    }
                }

            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if(dialogObject != null)
                    Marshal.ReleaseComObject(dialogObject);

                if (selectDevice != null)
                    Marshal.ReleaseComObject(selectDevice);
            }

            return doImort;
        }

        #endregion

        #region OutputFileNameTemplate

        /// <summary>
        /// Sets template that specifies the format of file names.
        /// </summary>
        /// <param name="fileNameTemplate">Format of file names.</param>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The specified parameter is not valid.
        /// </exception>
        public void SetOutputFilenameTemplate(string fileNameTemplate)
        {
            // Check for null argument.
            if (string.IsNullOrEmpty(fileNameTemplate))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterFileNameTemplate);

            // Check for maximum length of fileNameTemplate.
            if (fileNameTemplate.Length > 207)
                throw new ArgumentException(PictureAcquisitionResource.TemplateMaxLength);

            this.fileNameTemplate = fileNameTemplate;
        }

        /// <summary>
        /// Retrieves file name template.
        /// </summary>
        /// <returns>File name template.</returns>
        public string GetOutputFilenameTemplate()
        {
            return this.fileNameTemplate;
        }

        #endregion

        #region AcquisitionTime

        /// <summary>
        /// Sets the acquisition time of the current session. 
        /// </summary>
        /// <param name="timeToset">Time to set in acquisition time.</param>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public void SetAcquisitionTime(System.Runtime.InteropServices.ComTypes.FILETIME timeToset)
        {
            // Set to default value.
            errorResult = APIErrors.S_OK;

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            // Create object of IPhotoAcquireSettings.
            PictureAcquisitionNative.IPhotoAcquireSettings acquireSetting = null;

            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(selectedDeviceInfo.Id, out photoAcquireSource);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Get instance of setting object.
                errorResult = (APIErrors)photoAcquireSource.GetPhotoAcquireSettings(out acquireSetting);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());


                // Retrieve acquisition time.
                errorResult = (APIErrors)acquireSetting.SetAcquisitionTime(timeToset);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());
            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);
                
                if (acquireSetting != null)
                    Marshal.ReleaseComObject(acquireSetting);   
            }
        }

        /// <summary>
        /// Retrieves the acquisition time of the current session. 
        /// </summary>
        /// <returns>Acquisition time of the current session.</returns>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public System.Runtime.InteropServices.ComTypes.FILETIME GetAcquisitionTime()
        {
            // Set to default value.
            errorResult = APIErrors.S_OK;

            System.Runtime.InteropServices.ComTypes.FILETIME time = new System.Runtime.InteropServices.ComTypes.FILETIME();

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            // Create object of IPhotoAcquireSettings.
            PictureAcquisitionNative.IPhotoAcquireSettings acquireSetting = null;

            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(selectedDeviceInfo.Id, out photoAcquireSource);
                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());
                
                // Get instance of setting object.
                errorResult = (APIErrors)photoAcquireSource.GetPhotoAcquireSettings(out acquireSetting);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Retrieve acquisition time.
                errorResult = (APIErrors)acquireSetting.GetAcquisitionTime(out time);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);
                
                if (acquireSetting != null)
                    Marshal.ReleaseComObject(acquireSetting);                
            }
            return time;
        }
        #endregion

        #region GetImage

        /// <summary>
        /// Gets Image of all images inside specified device.
        /// </summary>
        /// <param name="deviceId">Id of Device, from which to get images.</param>
        /// <returns>List of image objects of images from specifeid device.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        /// <remarks>Consecutive call to this or any of these methods :
        /// GetImage,GetThumbnail and WpfGetThumbnail causes error of 
        /// "file being used by another process."</remarks>
        public List<System.Windows.Controls.Image> WpfGetImages(string deviceId)
        {
            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            List<System.Windows.Controls.Image> imageList = new List<System.Windows.Controls.Image>();

            // Create temporary files.
            List<string> imageNameList = this.CreateTemporaryFiles(deviceId);

            for (int index = 0; index < imageNameList.Count; index++)
            {
                // Create bitmapsource of newly created file.
                BitmapSource source = BitmapFrame.Create(new Uri(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + PictureAcquisitionResource.TempLocation + imageNameList[index]));

                imageList.Add(new System.Windows.Controls.Image());

                // Assign bitmapsource to source of Image.
                imageList[index].Source = source;

            }
            return imageList;
        }

        /// <summary>
        /// Gets Image of all images inside specified device.
        /// </summary>
        /// <param name="deviceId">Id of Device, from which to get images.</param>
        /// <returns>List of image objects of images from specifeid device.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        /// <remarks>Consecutive call to this or any of these methods :
        /// WpfGetImage,GetThumbnail and WpfGetThumbnail causes error of 
        /// "file being used by another process."</remarks>
        public List<System.Drawing.Image> GetImages(string deviceId)
        {
            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            List<System.Drawing.Image> imageList = new List<System.Drawing.Image>();

            // Create temporary files.
            List<string> imageNameList = this.CreateTemporaryFiles(deviceId);

            for (int index = 0; index < imageNameList.Count; index++)
            {
                // Create bitmapsource of newly created file.
                System.Drawing.Bitmap source = new System.Drawing.Bitmap(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + PictureAcquisitionResource.TempLocation + imageNameList[index]);
                imageList.Add((System.Drawing.Image)source);
                imageList[index].Tag = imageNameList[index];
            }
            return imageList;
        }

        #endregion

        #region GetThumbnail

        /// <summary>
        /// Gets Image of all images inside specified device.
        /// </summary>
        /// <param name="deviceId">Id of Device, from which to get images.</param>
        /// <returns>List of image objects of images from specifeid device.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        /// <remarks>Consecutive call to this or any of these methods :
        /// WpfGetImage,GetImage and WpfGetThumbnail causes error of 
        /// "file being used by another process."</remarks>
        public List<System.Drawing.Image> GetThumbnails(string deviceId)
        {
            // Get list of images.
            List<System.Drawing.Image> imageList = this.GetImages(deviceId);

            List<System.Drawing.Image> thumbnailList = new List<System.Drawing.Image>();

            System.Drawing.Image.GetThumbnailImageAbort imgCallBack = new System.Drawing.Image.GetThumbnailImageAbort(CallBackMethod);

            //Get thumbnails.
            for (int index = 0; index < imageList.Count; index++)
            {
                thumbnailList.Add(imageList[index].GetThumbnailImage(100, 100, imgCallBack, IntPtr.Zero));
                thumbnailList[index].Tag = imageList[index].Tag;
            }

            imageList.Clear();

            return thumbnailList;
        }

        /// <summary>
        /// Gets Image of all images inside specified device.
        /// </summary>
        /// <param name="deviceId">Id of Device, from which to get images.</param>
        /// <returns>List of image objects of images from specifeid device.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        /// <remarks>Consecutive call to this or any of these methods :
        /// WpfGetImage,GetThumbnail and WpfGetThumbnail causes error of 
        /// "file being used by another process."</remarks>
        public List<System.Windows.Controls.Image> WpfGetThumbnails(string deviceId)
        {
            // Get list of images.
            List<System.Windows.Controls.Image> imageList = this.WpfGetImages(deviceId);

            //Resize images to get thumbnails.
            for (int index = 0; index < imageList.Count; index++)
            {
                imageList[index].Width = 100;
                imageList[index].Height = 100;
            }

            return imageList;
        }

        #endregion

        /// <summary>
        /// Deletes specified item from specified device.
        /// </summary>
        /// <param name="itemName">Name of item to be deleted.</param>
        /// <param name="deviceId">Id of device from which specified delete will be deleted.</param>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The specified parameter is not valid.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public void DeleteItem(string itemName, string deviceId)
        {
            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            photoAcquireItem = null;

            // Check for null arguments.
            if (string.IsNullOrEmpty(itemName))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterItemName);

            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            List<string> itemList = this.GetDeviceItems(deviceId);

            if (!(itemList.Contains(itemName)))
                throw new ArgumentException(PictureAcquisitionResource.ItemNotFound);

            // Set to default value.
            errorResult = APIErrors.S_OK;

            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                UInt32 itemCount = 0;

                // Initialize list of items in speciefied device.
                errorResult = (APIErrors)photoAcquireSource.InitializeItemList(true, IntPtr.Zero, out itemCount);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                string deviceItemName;
                bool canDelete = false;

                // Serach for item to be deleted in the list of items.
                for (int index = 0; index < itemCount; index++)
                {
                    // Retrieve item from specified index.
                    errorResult = (APIErrors)photoAcquireSource.GetItemAt((UInt32)index, out photoAcquireItem);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    // Retrieve name of item.
                    errorResult = (APIErrors)photoAcquireItem.GetItemName(out deviceItemName);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    if (itemName == deviceItemName)
                    {
                        // Check whether item can be deleted from device or not.
                        errorResult = (APIErrors)photoAcquireItem.CanDelete(out canDelete);

                        if (canDelete && (errorResult == APIErrors.S_OK))
                        {
                            // Delete specified item from device.
                            errorResult = (APIErrors)photoAcquireItem.Delete();

                            if (errorResult != APIErrors.S_OK)
                                throw new PictureAcquisitionException(errorResult.ToString());
                            break;
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);

                if (photoAcquireItem != null)
                    Marshal.ReleaseComObject(photoAcquireItem);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);
            }
        }

        /// <summary>
        /// Retrieves list of picture and vedio items from specified device.
        /// </summary>
        /// <param name="deviceId">Id of device from which list of items is to be retrieved.</param>
        /// <returns>List of picture and video items of specified device.</returns>
        /// <exception cref="ArgumentNullException">
        /// The required parameter is null or empty.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The specified parameter is not valid.
        /// </exception>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public List<string> GetDeviceItems(string deviceId)
        {
            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            photoAcquireItem = null;

            // Check for null arguments.
            if (string.IsNullOrEmpty(deviceId))
                throw new ArgumentNullException(PictureAcquisitionResource.ParameterDeviceId);

            // Set to default value.
            errorResult = APIErrors.S_OK;
            
            List<string> itemList;

            try
            {
                photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                // Create photosource for acquiring items from.
                errorResult = (APIErrors)photoAcquire.CreatePhotoSource(deviceId, out photoAcquireSource);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                UInt32 itemCount = 0;

                // Initialize list of items in speciefied device.
                errorResult = (APIErrors)photoAcquireSource.InitializeItemList(true, IntPtr.Zero, out itemCount);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                // Create list of length equal to total items in the specified device.
                itemList = new List<string>((int)itemCount);

                string itemName;

                // Add item names in the list of items.
                for (int index = 0; index < itemCount; index++)
                {
                    // Retrieve item from specified index.
                    errorResult = (APIErrors)photoAcquireSource.GetItemAt((UInt32)index, out photoAcquireItem);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    // Retrieve name of item.
                    errorResult = (APIErrors)photoAcquireItem.GetItemName(out itemName);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    itemList.Add(itemName);
                }
            }
            catch (Exception exception)
            {
                if (exception.Message == PictureAcquisitionResource.ResultFileNotFound)
                    throw new ArgumentException(PictureAcquisitionResource.InvalidDeviceId);
                else
                    throw new PictureAcquisitionException(exception.Message);
            }
            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);
                
                if (photoAcquireItem != null)
                    Marshal.ReleaseComObject(photoAcquireItem);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);
            }
            return itemList;
        }

        /// <summary>
        /// Get the selected device details.
        /// </summary>
        /// <returns>Object of DeviceInfo class containing information of selected device.</returns>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public DeviceInfo GetSelectedDevice()
        {
            // Set to default value.
            errorResult = APIErrors.S_OK;

            string deviceFriendlyName;

            // Create the PhotoAcquire object.
            PictureAcquisitionNative.PhotoAcquire photoAcquireObject = null;
            PictureAcquisitionNative.IPhotoAcquire photoAcquire = null;

            PictureAcquisitionNative.IPhotoAcquireSource photoAcquireSource = null;

            try
            {
                if (selectedDeviceInfo != null)
                {
                    photoAcquireObject = new PictureAcquisitionNative.PhotoAcquire();
                    photoAcquire = (PictureAcquisitionNative.IPhotoAcquire)photoAcquireObject;

                    // Create photosource for acquiring items from.
                    errorResult = (APIErrors)photoAcquire.CreatePhotoSource(selectedDeviceInfo.Id, out photoAcquireSource);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    // Get friendly name of selected device.
                    errorResult = (APIErrors)photoAcquireSource.GetFriendlyName(out deviceFriendlyName);

                    if (errorResult != APIErrors.S_OK)
                        throw new PictureAcquisitionException(errorResult.ToString());

                    // Set friendly name of selcted device to the object property.
                    selectedDeviceInfo.FriendlyName = deviceFriendlyName;
                }
                else
                    throw new PictureAcquisitionException(PictureAcquisitionResource.DeviceNotSelected);
            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (photoAcquireObject != null)
                    Marshal.ReleaseComObject(photoAcquireObject);

                if (photoAcquire != null)
                    Marshal.ReleaseComObject(photoAcquire);

                if (photoAcquireSource != null)
                    Marshal.ReleaseComObject(photoAcquireSource);
            }

            return selectedDeviceInfo;
        }
        
        /// <summary>
        /// Shows dialog for doing import setting for various devices.
        /// </summary>
        /// <exception cref="PictureAcquisitionException">
        /// Call to native API has raised an error.
        /// </exception>
        public void ShowImportSettings()
        {
            // Set to default value.
            errorResult = APIErrors.S_OK;

            // Create the object of settings dialog.
            PictureAcquisitionNative.PhotoAcquireOptionsDialog optionDialogObject = null;
            PictureAcquisitionNative.IPhotoAcquireOptionsDialog optionDialog = null;

            try
            {
                optionDialogObject = new PictureAcquisitionNative.PhotoAcquireOptionsDialog();
                optionDialog = (PictureAcquisitionNative.IPhotoAcquireOptionsDialog)optionDialogObject;

                // Initialize import settings from registry.
                errorResult = (APIErrors)optionDialog.Initialize(null);

                if (errorResult != APIErrors.S_OK)
                    throw new PictureAcquisitionException(errorResult.ToString());

                Int32 settingResult = 0;

                // Show import settings dialog.
                errorResult = (APIErrors)optionDialog.DoModal(IntPtr.Zero, ref settingResult);

                if (errorResult != APIErrors.S_OK && (errorResult != APIErrors.S_FALSE))
                    throw new PictureAcquisitionException(errorResult.ToString());

                // If the user clicked OK, then save the updated settings.
                if (settingResult == 1)
                {
                    optionDialog.SaveData();
                }
            }
            catch (Exception exception)
            {
                throw new PictureAcquisitionException(exception.Message);
            }

            finally
            {
                if (optionDialogObject != null)
                    Marshal.ReleaseComObject(optionDialogObject);

                if (optionDialogObject != null)
                    Marshal.ReleaseComObject(optionDialog);
            }
        }       

        #endregion
    }
        
    #region Public classes

    /// <summary>
    /// Provides information about device.
    /// </summary>
    public class DeviceInfo
    {
        #region Private members

        /// <summary>
        /// Friendly name of device.
        /// </summary>
        private string friendlyName;

        /// <summary>
        /// Id of device.
        /// </summary>
        private string id;

        /// <summary>
        /// Type of device.
        /// </summary>
        private DeviceType type;
        
        #endregion

        #region Public properties
        
        /// <summary>
        /// Friendly name of device.
        /// </summary>
        public string FriendlyName
        {
            get { return friendlyName; }
            set { friendlyName = value; }
        }

        /// <summary>
        /// Id of device.
        /// </summary>
        public string Id
        {
            get { return id; }
            set { id = value; }
        }

        /// <summary>
        /// Type of device.
        /// </summary>
        public DeviceType Type
        {
            get { return type; }
            set { type = value; }
        }
      
        #endregion
    }
    #endregion

    #region Enumerations

    /// <summary>
    /// Specifies different types of device.
    /// </summary>
    public enum DeviceType
    {
        /// <summary>
        /// Specifies that the type of the selected device is unknown.
        /// </summary>
        Unknown = 0x00000000,

        /// <summary>
        /// Specifies that the type of the selected device is Windows Portable Devices (WPD).
        /// </summary>
        Wpd = 0x00000001,

        /// <summary>
        /// Specifies that the type of the selected device is Windows Image Acquisition (WIA).
        /// </summary>
        Wia = 0x00000002,

        /// <summary>
        /// Specifies that the type of the selected device is Still Image Architecture (STI).
        /// </summary>
        Sti = 0x00000003,

        /// <summary>
        /// Not supported.
        /// </summary>
        Twain = 0x00000004,

        /// <summary>
        /// Specifies that the selected device is a removable drive in the file system.
        /// </summary>
        FS = 0x00000005
    }

    /// <summary>
    /// Specifies different flags for device detection in device slection dialog.
    /// </summary>
    public enum DeviceFlag
    {
        /// <summary>
        /// None.
        /// </summary>
        None = 0x00000000,
        
        /// <summary>
        /// Specifies devices of type Windows Portable Devices (WPD).
        /// </summary>
        Wpd = 0x00000001,

        /// <summary>
        /// Specifies cameras of type Windows Image Acquisition (WIA).
        /// </summary>
        Cameras = 0x00000002,

        /// <summary>
        /// Specifies scanners of type Windows Image Acquisition (WIA).
        /// </summary>
        Scanners = 0x00000004,

        /// <summary>
        /// Specifies devices of type Still Image Architecture (STI).
        /// </summary>
        Sti = 0x00000008,

        /// <summary>
        /// Specifies removable storage devices, such as CD drives or Pan drive.
        /// </summary>
        FS = 0x00000020,

        /// <summary>
        /// Specifies removable storage devices, such as CD drives or card readers.
        /// </summary>
        CardReaders = 0x00000020,

        /// <summary>
        /// Specifies digital video camera devices.
        /// </summary>
        DigitalVideoCameras = 0x00000040,

        /// <summary>
        /// Specifies all devices.
        /// </summary>
        All = 0x0000FFFF,

        /// <summary>
        /// Specifies devices that are offline.  Not supported by all device types.
        /// </summary>
        OffLine = 0x00020000
    }

    internal enum APIErrors : uint
    {
        /// <summary>
        /// Invalid argument.
        /// </summary>
        E_INVALIDARG = 0x80070057,

        /// <summary>
        /// The system cannot find the file specified
        /// </summary>
        FILE_NOT_FOUND = 0x80070002,

        /// <summary>
        /// The operation completed successfully.
        /// </summary>
        S_OK = 0x00000000,

        /// <summary>
        /// Incorrect function.
        /// </summary>
        S_FALSE = 0x00000001,

        /// <summary>
        /// Operation aborted.
        /// </summary>
        E_ABORT =0x80004004, 

        /// <summary>
        /// Unspecified error. 
        /// </summary>
        E_FAIL =0x80004005, 

        /// <summary>
        /// Interface not supported. 
        /// </summary>
        E_NOINTERFACE =0x80004002,

        /// <summary>
        /// Not implemented. 
        /// </summary>
        E_NOTIMPL =0x80004001,

        /// <summary>
        /// Invalid pointer. 
        /// </summary>
        E_POINTER= 0x80004003, 

        /// <summary>
        /// Catastrophic failure. 
        /// </summary>
        E_UNEXPECTED =0x8000FFFF 
    }

    #endregion
}
